#include "ota_func.h"
#include "FSMC_SRAM.h"
#include "cJSON.h"
#include "cJSON_static_mem.h"
#include "device_resource.h"
#include "mbedtls/sha256.h"
#include "mqttclient.h"
#include "print_rtt.h"
#include "private_mqtt_analyse.h"
#include "spi_flash_op.h"
#include "string.h"
#include <stdlib.h>
uint8_t *read_from_spi_flash_buffer = (uint8_t *)READ_FROM_SPI_BUFFER;
OTA_PROCESS_INFO *ota_process_info = (OTA_PROCESS_INFO *)MQTT_OTA_PROCESS_INFO; // ----------------------------------------

// 1. 定义字符串常量 (对应 Python 的 FW_*_ATTR)
#define FW_CHECKSUM_ATTR     "fw_checksum"
#define FW_CHECKSUM_ALG_ATTR "fw_checksum_algorithm"
#define FW_SIZE_ATTR         "fw_size"
#define FW_TITLE_ATTR        "fw_title"
#define FW_VERSION_ATTR      "fw_version"
#define FW_STATE_ATTR        "fw_state"

// 注意：FW_STATE_ATTR 不包含在 REQUIRED_SHARED_KEYS 中
#define REQUIRED_SHARED_KEYS FW_CHECKSUM_ATTR "," FW_CHECKSUM_ALG_ATTR "," FW_SIZE_ATTR "," FW_TITLE_ATTR "," FW_VERSION_ATTR

void publish_firmware_info_request(void)
{
  char topic[128];       // 用于存储生成的主题
  char *json_str = NULL; // 用于存储生成的 JSON 字符串
  int32_t topic_len;
  size_t mark = cJSON_StaticMem_TakeMark(); // ① 打标记
#ifdef MQTT_CLIENT_DEBUG
  LOG_COLOR(YELLOW, "CJSON_MARK :%d\n", mark);
#endif
  cJSON *root = cJSON_CreateObject();
  int32_t result;

  // 6. 递增 request_id
  ota_process_info->request_id++;
  // topic = f"v1/devices/me/attributes/request/{self.__request_id}"
  topic_len = snprintf(topic, sizeof(topic), "v1/devices/me/attributes/request/%u", ota_process_info->request_id);
  // 检查是否截断
  if (topic_len >= sizeof(topic) || topic_len < 0)
  {
#ifdef MQTT_CLIENT_DEBUG
    LOG_ERROR("[ERROR] Topic string too long or error\n");
#endif
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    goto CLEAN_AND_EXIT;
  }
#ifdef MQTT_CLIENT_DEBUG
  // 8. 打印调试信息 (可选)
  LOG_INFO("[INFO] Published to topic: %s (QoS=%d)\n", topic, 1);
  LOG_INFO("       Payload (request): Request firmware info (ID: %u)\n", ota_process_info->request_id);
#endif

  // 9. 使用 cJSON 构造 JSON 负载

  if (root == NULL)
  {
#ifdef MQTT_CLIENT_DEBUG
    LOG_ERROR("[ERROR] Failed to create cJSON object\n");
#endif
    goto CLEAN_AND_EXIT;
  }
  // 添加 "sharedKeys" 键值对
  cJSON_AddStringToObject(root, "sharedKeys", REQUIRED_SHARED_KEYS);

  // 将 cJSON 对象转换为格式化的字符串
  json_str = cJSON_PrintUnformatted(root); // 不带缩进，更紧凑
  if (json_str == NULL)
  {
#ifdef MQTT_CLIENT_DEBUG
    LOG_ERROR("[ERROR] Failed to print JSON\n");
#endif
    goto CLEAN_AND_EXIT;
  }
  // 10. 调用 MQTT 发布函数
  // MQTTMsgPublish(MQTT_BUFFER, MQTT_BUFFER_LENTH, (char *)PUBLISH_OTA_CURRENT_STATUS_TOPIC, QOS1, json_str, strlen(json_str));
  // 注意：这里 topic 是我们构造的，不是 PUBLISH_OTA_CURRENT_STATUS_TOPIC
  result = MQTTMsgPublish(
      MQTT_BUFFER,         // 假设是全局缓冲区
      MQTT_BUFFER_LENTH,   // 缓冲区大小
      topic,               // 主题
      QOS1,                // QoS=1
      (uint8_t *)json_str, // payload (JSON 字符串)
      strlen(json_str)     // payload 长度
  );

  if (result >= 0)
  { // 假设 0 表示成功，具体看您的 API
#ifdef MQTT_CLIENT_DEBUG
    LOG_INFO("[INFO] Publish successful\n");
#endif
  }
  else
  {
#ifdef MQTT_CLIENT_DEBUG
    LOG_ERROR("[ERROR] Publish failed\n");
#endif
  }
CLEAN_AND_EXIT:
#ifdef MQTT_CLIENT_DEBUG
  LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
  cJSON_StaticMem_Rollback(mark);
}

// 函数：检查主题并提取 request_id
// 返回值：0=不匹配, >0=request_id
// ----------------------------------------
uint32_t match_and_extract_request_id(const char *topic)
{
  const char *prefix = "v1/devices/me/attributes/response/";
  int prefix_len = strlen(prefix);

  // 检查前缀是否匹配
  if (strncmp(topic, prefix, prefix_len) != 0)
  {
    return 0; // 不匹配
  }

  // 获取 ID 部分（从 prefix_len 开始）
  const char *id_str = topic + prefix_len;

  // 可以在这里添加验证：确保 id_str 只包含数字等
  // 简单起见，直接转换
  return (uint32_t)atoi(id_str);
}

// ----------------------------------------
// 函数：解析固件属性 JSON 负载
// 返回值：0=成功, -1=失败
// ----------------------------------------
int parse_firmware_attributes(const char *payload, OTA_PROCESS_INFO *info)
{
  cJSON *root = NULL;
  cJSON *shared_obj = NULL;
  // 3. 逐个提取字段
  cJSON *item = NULL;
  size_t mark = cJSON_StaticMem_TakeMark(); // ① 打标记
#ifdef MQTT_CLIENT_DEBUG
  LOG_COLOR(YELLOW, "CJSON_MARK :%d\n", mark);
#endif
  // 1. 解析整个 JSON 字符串
  root = cJSON_Parse(payload);
  if (root == NULL)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[ERROR] Failed to parse JSON payload\n");
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }

  // 2. 获取 "shared" 对象
  shared_obj = cJSON_GetObjectItem(root, "shared");
  if (shared_obj == NULL)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[ERROR] 'shared' object not found in JSON\n");
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }

  // fw_checksum (字符串)
  item = cJSON_GetObjectItem(shared_obj, "fw_checksum");
  if (cJSON_IsString(item) && (item->valuestring != NULL))
  {
    strncpy(info->fw_checksum, item->valuestring, sizeof(info->fw_checksum) - 1);
    info->fw_checksum[sizeof(info->fw_checksum) - 1] = '\0'; // 确保结束
  }
  else
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[WARN] 'fw_checksum' missing or invalid\n");
    info->fw_checksum[0] = '\0';
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }

  // fw_size (数字)
  item = cJSON_GetObjectItem(shared_obj, "fw_size");
  if (cJSON_IsNumber(item))
  {
    info->fw_size = (uint32_t)item->valueint;
  }
  else
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[WARN] 'fw_size' missing or invalid\n");
    info->fw_size = 0;
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }

  // fw_title (字符串)
  item = cJSON_GetObjectItem(shared_obj, "fw_title");
  if (cJSON_IsString(item) && (item->valuestring != NULL))
  {
    strncpy(info->fw_title, item->valuestring, sizeof(info->fw_title) - 1);
    info->fw_title[sizeof(info->fw_title) - 1] = '\0';
  }
  else
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[WARN] 'fw_title' missing or invalid\n");
    info->fw_title[0] = '\0';
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }

  // fw_checksum_algorithm (字符串)
  item = cJSON_GetObjectItem(shared_obj, "fw_checksum_algorithm");
  if (cJSON_IsString(item) && (item->valuestring != NULL))
  {
    strncpy(info->fw_checksum_algorithm, item->valuestring, sizeof(info->fw_checksum_algorithm) - 1);
    info->fw_checksum_algorithm[sizeof(info->fw_checksum_algorithm) - 1] = '\0';
  }
  else
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[WARN] 'fw_checksum_algorithm' missing or invalid\n");
    info->fw_checksum_algorithm[0] = '\0';
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }

  // fw_version (字符串)
  item = cJSON_GetObjectItem(shared_obj, "fw_version");
  if (cJSON_IsString(item) && (item->valuestring != NULL))
  {
    strncpy(info->fw_version, item->valuestring, sizeof(info->fw_version) - 1);
    info->fw_version[sizeof(info->fw_version) - 1] = '\0';
  }
  else
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[WARN] 'fw_version' missing or invalid\n");
    info->fw_version[0] = '\0';
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }
#ifdef MQTT_CLIENT_DEBUG
  LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
  cJSON_StaticMem_Rollback(mark);
  return 0;
}

// ----------------------------------------
// 模拟的 MQTT 回调函数
// ----------------------------------------
int mqtt_message_callback(const char *topic, const uint8_t *msg, uint16_t msg_len)
{
#ifdef OTA_DEBUG
  LOG_INFO("[INFO] Received message on topic: %s\n", topic);
#endif // !1

  // 1. 尝试匹配主题并提取 request_id
  ota_process_info->request_id = match_and_extract_request_id(topic);
  if (ota_process_info->request_id == 0)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[INFO] Topic does not match expected pattern\n");
#endif // !1

    return -1;
  }
#ifdef OTA_DEBUG
  LOG_INFO("[INFO] Matched request ID: %u\n", ota_process_info->request_id);
#endif // !1
  // 3. 解析 JSON 负载
  if (parse_firmware_attributes((char *)msg, ota_process_info) != 0)
  {

#ifdef OTA_DEBUG
    LOG_ERROR("[ERROR] Failed to parse firmware attributes\n");
#endif // !1

    return -1;
  }
  // 4. 打印解析结果

#ifdef OTA_DEBUG
  LOG_INFO("[SUCCESS] Firmware Attributes Parsed:\n");
  LOG_INFO("  FW Checksum: %s\n", ota_process_info->fw_checksum);
  LOG_INFO("  FW Size: %u bytes\n", ota_process_info->fw_size);
  LOG_INFO("  FW Title: %s\n", ota_process_info->fw_title);
  LOG_INFO("  Checksum Algorithm: %s\n", ota_process_info->fw_checksum_algorithm);
  LOG_INFO("  FW Version: %s\n", ota_process_info->fw_version);
#endif // !1
  ota_process_info->left_fw_size = ota_process_info->fw_size;
  ota_process_info->current_package_index = 0;
  ////
  return 0;
}
int get_firmware(uint32_t request_id,
                 uint16_t current_package_index,
                 uint32_t chunk_size)
{
  char payload_str[16]; // 存储 chunk_size 的字符串形式
  char topic[64];
  uint8_t *payload_ptr; // 指向实际 payload 的指针
  uint16_t payload_len; // payload 的长度
  int32_t topic_len;
  int8_t qos = 1;
  // 1. 构造主题
  // topic = f"v2/fw/request/{self.__firmware_request_id}/chunk/{self.__current_chunk}"
  topic_len = snprintf(topic,
                       64,
                       "v2/fw/request/%u/chunk/%u",
                       request_id,
                       current_package_index);

  if (topic_len >= 64 || topic_len < 0)
  {
#ifdef OTA_DEBUG

    LOG_ERROR("[ERROR] Topic string too long or error\n");
#endif // !1

    return -1;
  }

  //  3. 打印调试信息
  if (chunk_size > 0)
  {
#ifdef OTA_DEBUG

    LOG_INFO("[INFO] Published to topic: %s (QoS=%d)\n", topic, qos);
    LOG_INFO("       Payload (fw request): Chunk size: %u bytes (Chunk: %u)\n",
             chunk_size,
             current_package_index);
#endif // !1

    // 4. 将 chunk_size 转换为字符串 -> payload
    snprintf(payload_str, sizeof(payload_str), "%u", chunk_size);
    payload_ptr = (uint8_t *)payload_str;
    payload_len = strlen(payload_str);
  }
  else
  {

#ifdef OTA_DEBUG
    LOG_INFO("[INFO] Published to topic: %s (QoS=%d)\n", topic, qos);
    LOG_INFO("       Payload (fw request): Default chunk size (Chunk: %u)\n",
             current_package_index);
#endif // !1

    // 5. 空 payload
    payload_ptr = NULL;
    payload_len = 0;
  }
  // 6. 打印 payload 信息 (用于调试，类似 Python 的 print)
#ifdef OTA_DEBUG
  LOG_INFO("Payload length: %u\n", payload_len);
  if (payload_len > 0)
  {
    LOG_INFO("Payload char: ");
    LOG_INFO("%s \n", payload_str);
  }
#endif // !1

  //   // 7. 调用 MQTT 发布函数
  // 注意：如果 payload_len == 0，payload_ptr 可以是 NULL 或指向空字符串
  int32_t result = MQTTMsgPublish(
      MQTT_BUFFER,                                     // 缓冲区
      MQTT_BUFFER_LENTH,                               // 缓冲区大小
      topic,                                           // 主题
      qos,                                             // QoS
      (payload_len > 0) ? payload_ptr : (uint8_t *)"", // payload
      payload_len                                      // payload 长度
  );
  if (result < 0)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[ERROR] Failed to publish firmware request\n");
#endif // !1

    return -1;
  }
  else
  {
#ifdef OTA_DEBUG
    LOG_INFO("[INFO] Firmware request published successfully\n");
#endif // !1
  }
  return 0;
}
int extract_ids_from_topic(const char *topic, uint32_t *request_id, uint32_t *chunk_index)
{
  int ret;

  // 使用 sscanf 按格式解析
  ret = sscanf(topic, "v2/fw/response/%u/chunk/%u", request_id, chunk_index);

  // sscanf 返回成功匹配并赋值的参数个数
  if (ret != 2)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[ERROR] Failed to parse topic: %s\n", topic);
#endif // !1
    return -1;
  }
#ifdef OTA_DEBUG
  LOG_INFO("[INFO] Parsed - Request ID: %u, Chunk Index: %u\n", *request_id, *chunk_index);
#endif // !1
  return 0;
}

// ------------------------
// MQTT 配置宏定义
// ------------------------
#define OTA_TELEMETRY_TOPIC "v1/devices/me/telemetry"
#define OTA_TELEMETRY_QOS   1

// ------------------------
// 固件属性宏定义 (对应 Python 的 FW_*_ATTR)
// ------------------------
#define FW_TITLE_ATTR   "fw_title"
#define FW_VERSION_ATTR "fw_version"
#define FW_STATE_ATTR   "fw_state"
// ------------------------
// 固件信息长度（关键！）
// ------------------------
#define FW_TITLE_LENGTH   11 // 从 0x800C500 读 11 字节
#define FW_VERSION_LENGTH 6  // 从 0x800C513 读 6 字节
// ------------------------
// 临时缓冲区大小（加1用于 \0）
// ------------------------
#define FW_TITLE_BUF_SIZE   (FW_TITLE_LENGTH + 1)
#define FW_VERSION_BUF_SIZE (FW_VERSION_LENGTH + 1)
int send_to_server_ota_status(char *fw_title, char *fw_version, char *status)
{
  char *json_str = NULL;
  //  int32_t json_len;
  int32_t result;
  size_t mark = cJSON_StaticMem_TakeMark(); // ① 打标记
#ifdef MQTT_CLIENT_DEBUG
  LOG_COLOR(YELLOW, "CJSON_MARK :%d\n", mark);
#endif
  char title_buf[FW_TITLE_BUF_SIZE];     // [8]
  char version_buf[FW_VERSION_BUF_SIZE]; // [7]
  // 1. 创建 cJSON 对象
  cJSON *root = cJSON_CreateObject();
  if (root == NULL)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[ERROR] Failed to create cJSON object\n");
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }

  if (fw_title != NULL)
  {
    memcpy(title_buf, fw_title, FW_TITLE_LENGTH);
    title_buf[FW_TITLE_LENGTH] = '\0'; // 手动添加结束符
  }
  else
  {
    strcpy(title_buf, "unknown");
  }

  if (fw_version != NULL)
  {
    memcpy(version_buf, fw_version, FW_VERSION_LENGTH);
    version_buf[FW_VERSION_LENGTH] = '\0'; // 手动添加结束符
  }
  else
  {
    strcpy(version_buf, "unknown");
  }

  // 3. 添加字段（现在可以安全使用旧版 cJSON 函数）
  cJSON_AddStringToObject(root, "current_" FW_TITLE_ATTR, title_buf);
  cJSON_AddStringToObject(root, "current_" FW_VERSION_ATTR, version_buf);
  cJSON_AddStringToObject(root, FW_STATE_ATTR, (status != NULL) ? status : "UNKNOWN");

  // 4. 生成 JSON
  json_str = cJSON_PrintUnformatted(root);
  if (json_str == NULL)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[ERROR] Failed to print JSON\n");
#endif // !1
#ifdef MQTT_CLIENT_DEBUG
    LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
    cJSON_StaticMem_Rollback(mark);
    return -1;
  }
#ifdef OTA_DEBUG
  // 5. 打印调试
  LOG_INFO("[INFO] Published to topic: %s (QoS=%d)\n", OTA_TELEMETRY_TOPIC, OTA_TELEMETRY_QOS);
  LOG_INFO("       Payload (OTA status): %s\n", json_str);
#endif // !1

  // 5. 调用 MQTT 发布函数
  result = MQTTMsgPublish(
      MQTT_BUFFER,
      MQTT_BUFFER_LENTH,
      OTA_TELEMETRY_TOPIC,
      OTA_TELEMETRY_QOS,
      (uint8_t *)json_str,
      (uint16_t)strlen(json_str));

  // 6. 检查结果
  if (result < 0)
  {
#ifdef OTA_DEBUG
    LOG_ERROR("[WARNING] Failed to publish OTA status to %s\n", OTA_TELEMETRY_TOPIC);
#endif // !1
  }
  else
  {
#ifdef OTA_DEBUG
    LOG_INFO("[INFO] OTA status published successfully\n");
#endif // !1
  }
  // 7. 清理内存
#ifdef MQTT_CLIENT_DEBUG
  LOG_COLOR(YELLOW, "rollback CJSON_MARK :%d\n", mark);
#endif
  cJSON_StaticMem_Rollback(mark);
  return (result == 0) ? 0 : -1;
}
int save_bin_to_target_store(uint32_t address, uint8_t *data, uint32_t size)
{
  return SPIFlash_Write1K_InBound(FLASH_OTA_START + address, data, read_from_spi_flash_buffer, size);
}
int SPIFlash_SHA256_Stream(uint32_t addr, uint32_t total_len, uint8_t *buf, uint8_t hash[32])
{
  mbedtls_sha256_context ctx;
  uint32_t left = total_len;
  int ret = 0;
  mbedtls_sha256_init(&ctx);
  mbedtls_sha256_starts(&ctx, 0); /* 0 = SHA-256 */
  while (left > 0)
  {
    uint32_t chunk = (left > sizeof(buf)) ? sizeof(buf) : left;
    /* 读 1 KB（或剩余尾块）*/
    SoftSPIFlash_Read(addr, buf, chunk);
    mbedtls_sha256_update(&ctx, buf, chunk);
    addr += chunk;
    left -= chunk;
  }
  mbedtls_sha256_finish(&ctx, hash);
  mbedtls_sha256_free(&ctx);
  return ret;
}
